#include "internal.h"
#include "mocker_mgr.h"
#include <iostream>
#include <unordered_map>


template <typename F>
struct ApiHook {
};

template <typename R, typename T>
struct ApiHook<R(T)> {
private:
  static R Hook(T t1) {
    return reinterpret_cast<R(*)(T)>(HookObjectMgr::GetInstance().
      Invoke(m_apiAddress))(t1);
  }

public:
  static AddrModifier& MakeHook(void* api) {
    m_apiAddress = api;
    return HookObjectMgr::GetInstance().MakeHookObj(m_apiAddress, GetHook());
  }

  static void RemoveHook() {
    HookObjectMgr::GetInstance().RemoveHookObj(m_apiAddress);
  }

  static void* GetHook() { return reinterpret_cast<void*>(Hook); }

private:
  static inline void* m_apiAddress = nullptr;
};

#define MOCK(api, stub) \
    ApiHook<decltype(api)>::MakeHook(reinterpret_cast<void*>(api)).SetMethod(reinterpret_cast<void*>(stub))


#define UNMOCK(api) ApiHook<decltype(api)>::RemoveHook()

int FuncStub(int param) {
  std::cout << __FUNCTION__ << std::endl;
  return param;
}

int Func(int param) {
  std::cout << __FUNCTION__ << std::endl;
  return param;
}

int main() {
  Func(0);

  Mocker mocker{Func, FuncStub};
  Func(0);
  return 0;
}